package com.itgaohe.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itgaohe.common.context.UserContext;
import com.itgaohe.dao.entity.Blog;
import com.itgaohe.dao.entity.Like;
import com.itgaohe.dao.entity.User;
import com.itgaohe.dao.mapper.BlogMapper;
import com.itgaohe.dao.mapper.LikeMapper;
import com.itgaohe.dao.mapper.UserMapper;
import com.itgaohe.dto.UserDTO;
import com.itgaohe.dto.resp.CursorResponseDTO;
import com.itgaohe.dto.resp.SearchBlogDTO;
import com.itgaohe.service.BlogService;
import com.itgaohe.utils.CreateCursorUtil;
import com.itgaohe.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.itgaohe.common.constant.RedisConstants.CACHE_LIKE_KEY;
import static com.itgaohe.common.constant.RedisConstants.SYNC_SET_KEY;

@Slf4j
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService {
    @Autowired
    private BlogMapper blogMapper;
    @Autowired
    private LikeMapper likeMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private UserMapper userMapper;

    @Override
    public Result getBlogBykeyId(Long cursor) {
        UserDTO user = UserContext.getUser();
        Long userId = user.getId();

        if (cursor == 1) {
            cursor = CreateCursorUtil.initCursor();
        }
        CursorResponseDTO<Blog> cursors = new CursorResponseDTO<>() ;
        cursors.setHasMore(true);
        List<Blog> blogbyId = blogMapper.getBlogbyId(userId, cursor);
        if (blogbyId == null || blogbyId.size() == 0) {
            cursors.setHasMore(false);
            return Result.ok(cursors);
        }
        Long nextCursor = blogbyId.get(blogbyId.size() - 1).getCursorIndex() ;
        if (blogbyId.size() <  10) {
            cursors.setHasMore(false);
        }
        cursors.setNextCursor(nextCursor);
        cursors.setData(blogbyId);
        return Result.ok(cursors);
    }
    @Override
    public SearchBlogDTO getBlogById(Long id) {
        Blog blog = blogMapper.selectById(id);
        SearchBlogDTO searchBlogDTO = BeanUtil.copyProperties(blog, SearchBlogDTO.class);
        Long userId = blog.getUserId();
        User user = userMapper.selectById(userId);
        searchBlogDTO.setName(user.getNickName());
        searchBlogDTO.setIcon(user.getIcon());
        Long meid = UserContext.getUser().getId();
        LambdaQueryWrapper<Like> likeLambdaQueryWrapper =new LambdaQueryWrapper<>();
        likeLambdaQueryWrapper.eq(meid !=null ,Like::getUserId,meid)
                .eq(meid !=null ,Like::getBlogId,blog.getId());
        Like like = likeMapper.selectOne(likeLambdaQueryWrapper);
        if (like != null) {
            searchBlogDTO.setIsLike(0);
        }else {
            searchBlogDTO.setIsLike(1);
        }
        return searchBlogDTO;
    }
    @Override
    public Result getBlogbyUserId(Long userId,Long cursor) {
        if (cursor == 1) {
            cursor = CreateCursorUtil.initCursor() ;
        }
        CursorResponseDTO<Blog> cursors = new CursorResponseDTO<>() ;
        cursors.setHasMore(true);
        List<Blog> blogbyUserId = blogMapper.getBlogbyUserId(userId, cursor);
        if (blogbyUserId == null || blogbyUserId.size() == 0) {
            cursors.setHasMore(false);
            return Result.ok(cursors);
        }
        Long nextCursor = blogbyUserId.get(blogbyUserId.size() - 1).getCursorIndex() ;
        if (blogbyUserId.size() <  10) {
            cursors.setHasMore(false);
        }
        cursors.setNextCursor(nextCursor);
        cursors.setData(blogbyUserId);
        return Result.ok(cursors);
    }
    @Override
    public Result getBlogslist(Long cursor) {
        if (cursor == 1) {
            cursor = CreateCursorUtil.initCursor() ;
        }
        CursorResponseDTO<SearchBlogDTO> cursors = new CursorResponseDTO<>() ;
        cursors.setHasMore(true);
        List<Blog> blogslist = blogMapper.getBlogslist(cursor);
        if (blogslist == null || blogslist.size() == 0) {
            cursors.setHasMore(false);
            return Result.ok(cursors);
        }
        List<SearchBlogDTO> blogDTOListcopy = BeanUtil.copyToList(blogslist, SearchBlogDTO.class);
        Long meid = UserContext.getUser().getId();
        for (SearchBlogDTO searchBlogDTO : blogDTOListcopy) {
                Long userId = searchBlogDTO.getUserId();
                User user = userMapper.selectById(userId);
                searchBlogDTO.setName(user.getNickName());
                searchBlogDTO.setIcon(user.getIcon());
                LambdaQueryWrapper<Like> likeLambdaQueryWrapper =new LambdaQueryWrapper<>();
                likeLambdaQueryWrapper.eq(meid !=null ,Like::getUserId,meid)
                        .eq(meid !=null ,Like::getBlogId,searchBlogDTO.getId());
                Like like = likeMapper.selectOne(likeLambdaQueryWrapper);
                if (like != null) {
                    searchBlogDTO.setIsLike(0);
                }else {
                    searchBlogDTO.setIsLike(1);
                }
        }
        Long nextCursor = blogslist.get(blogslist.size() - 1).getCursorIndex() ;
        if (blogslist.size() <  6) {
            cursors.setHasMore(false);
        }
        cursors.setNextCursor(nextCursor);
        cursors.setData(blogDTOListcopy);
        return Result.ok(cursors);
    }


    /*
     * 博客点赞业务逻辑
     * */
    @Override
    // 点赞/取消点赞
    public Result likeBlog(Long blogId) {
        Long userId = UserContext.getUser().getId();
        String key = CACHE_LIKE_KEY + userId +blogId;


        if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
            // Redis中存在记录（点赞状态）
            redisTemplate.delete(key);
            redisTemplate.opsForSet().remove(SYNC_SET_KEY, key);
        } else if (blogMapper.existsLike(userId, blogId) > 0) {
            // 数据库中存在记录
            blogMapper.deleteLike(userId, blogId);
        } else {
            // 新增点赞
            Like like = new Like();
//            like.setId();
            like.setUserId(userId);
            like.setBlogId(blogId);
            //like.setCreateTime(LocalDateTime.now());
            redisTemplate.opsForValue().set(key, like);
            redisTemplate.opsForSet().add(SYNC_SET_KEY, key);
        }
        return Result.ok();


    }

    @Override
    public Integer blogAllLike(Long blogId) {
        Long userId = UserContext.getUser().getId();
        likeMapper.insertLike(blogId,userId,LocalDateTime.now());

        int likes = likeMapper.countLike(blogId);
        return likes;
    }

    // 同步Redis数据到数据库
    @Scheduled(fixedRate = 5000) // 30秒执行一次
    public void addDatabase() {
//        log.info("定时任务开始了");
        Set<Object> keys = redisTemplate.opsForSet().members(SYNC_SET_KEY);
        if (keys == null || keys.isEmpty()) return;

        for (Object keyObj : keys) {
            String key = (String) keyObj;
            Like like = (Like) redisTemplate.opsForValue().get(key);

            if (like != null) {
                likeMapper.insertLike(
                        like.getUserId(),
                        like.getBlogId(),
                        LocalDateTime.now());
                redisTemplate.opsForSet().remove(SYNC_SET_KEY, key);
            }
        }
    }
}






